//#include <iostream>
//#include <stdarg.h>
#include "rule.h"
#include "grammar.h"

void
grammar::print(ostream& out_stream)
{
  out_stream << "Terminals={";
  set<string>::const_iterator iter;
  int first=1;
  for (iter=Terminals.begin(); iter != Terminals.end(); iter++){
    if (first)
      first=0;
    else
      out_stream << ", ";
    out_stream << (*iter);
  }
  out_stream << "}" << endl;
  out_stream << "NonTerminals={";
  first=1;
  for (iter=NonTerminals.begin(); iter != NonTerminals.end(); iter++){
    if (first)
      first=0;
    else
      out_stream << ", ";
    out_stream << (*iter);
  }
  out_stream << "}" << endl;
  out_stream << "Initial=" << Initial << endl;
  out_stream << "Rules={\n\t";
  RULESET::const_iterator iterRules;
  first=1;
  for (iterRules=Rules.begin(); iterRules != Rules.end(); iterRules++){
    if (first)
      first=0;
    else
      out_stream << "\t";
    out_stream << "\t";
    (*iterRules)->print(out_stream);
    out_stream << "\n";
  }
  out_stream << "}" << endl;
}

void
grammar::addRule(string lhs, vector<string> rhs, class features *sem)
{
  class rule *r=new rule(lhs, rhs, sem);
  Rules.insert(r);
}

void
grammar::addNonTerminal(string s)
{
  NonTerminals.insert(s);
}

void
grammar::addTerminal(string s)
{
  Terminals.insert(s);
}

rule *
grammar::addNewInitial(string l)
{
  rule *r;
  vector< string > rhs;
  rhs.push_back(getInitial());
  Terminals.insert("_END_");
  rhs.push_back("_END_");
  r=new rule(l, rhs, NULL);
  Rules.insert(r);
  NonTerminals.insert(l);
  Initial=l;
  return r;
}

int
grammar::isTerminate(string s)
{
  set<string>::const_iterator iter=Terminals.find(s);
  return (iter != Terminals.end());
} 

int
grammar::isNonTerminate(string s)
{
  set<string>::const_iterator iter=NonTerminals.find(s);
  return (iter != NonTerminals.end());
} 

void
grammar::findTerms()
{
  NonTerminals.clear();
  Terminals.clear();

  RULESET::const_iterator iterRules;
  for (iterRules=Rules.begin(); iterRules != Rules.end(); iterRules++){
    NonTerminals.insert((*iterRules)->getLhs());
  }
  for (iterRules=Rules.begin(); iterRules != Rules.end(); iterRules++){
    unsigned int i;
    for(i=0; i<(*iterRules)->getRhs().size(); i++){
      if (NonTerminals.find((*iterRules)->getRhs()[i])==NonTerminals.end()){
	Terminals.insert((*iterRules)->getRhs()[i]);
      }
    }
  }
}
